﻿using Microsoft.IdentityModel.Tokens;
using System.Text;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Utils;
using System.Net;
using TrafficWebApi.Models.Response;

namespace TrafficWebApi.Services
{
    public static class AuthorizationSetup
    {
        #region PageCls
        //private static FixedAsset.BLL.S_UserToken TokenBll = new FixedAsset.BLL.S_UserToken();
        #endregion

        /// <summary>
        /// 增加验证头
        /// </summary>
        /// <param name="services"></param>
        /// <exception cref="ArgumentNullException"></exception>
        public static void AddAuthorizationSetup(this IServiceCollection services)
        {
            if (services == null) throw new ArgumentNullException(nameof(services));

            // 1【授权】、这个和上边的异曲同工，好处就是不用在controller中，写多个 roles 。
            // 然后这么写 [Authorize(Policy = "Admin")]
            services.AddAuthorization(options =>
            {
                options.AddPolicy("User", policy => policy.RequireRole("User").Build());
                options.AddPolicy("System", policy => policy.RequireRole("System").Build());
                options.AddPolicy("SystemOrAdmin", policy => policy.RequireRole("Admin", "System"));
            });

            var AppSettings = new ConfigurationBuilder().SetBasePath(Directory.GetCurrentDirectory()).AddJsonFile("appsettings.json", optional: false, reloadOnChange: true).Build();

            //读取配置文件
            var symmetricKeyAsBase64 = AppSettings.GetSection("AppSettings:JwtSetting:SecretKey").Value;
            var keyByteArray = Encoding.ASCII.GetBytes(symmetricKeyAsBase64);
            var signingKey = new SymmetricSecurityKey(keyByteArray);
            var Issuer = AppSettings.GetSection("AppSettings:JwtSetting:Issuer").Value;
            var Audience = AppSettings.GetSection("AppSettings:JwtSetting:Audience").Value;

            // 令牌验证参数
            var tokenValidationParameters = new TokenValidationParameters
            {
                ValidateIssuerSigningKey = true,
                IssuerSigningKey = signingKey,
                ValidateIssuer = true,
                ValidIssuer = Issuer,//发行人
                ValidateAudience = true,
                ValidAudience = Audience,//订阅人
                ValidateLifetime = true,
                ClockSkew = TimeSpan.FromSeconds(30),
                RequireExpirationTime = true,
            };

            //2.1【认证】、core自带官方JWT认证
            // 开启Bearer认证
            services.AddAuthentication("Bearer")
             // 添加JwtBearer服务
             .AddJwtBearer(o =>
             {
                 o.TokenValidationParameters = tokenValidationParameters;
                 o.Events = new JwtBearerEvents
                 {
                     OnAuthenticationFailed = context =>
                     {
                         // 如果过期，则把<是否过期>添加到，返回头信息中
                         if (context.Exception.GetType() == typeof(SecurityTokenExpiredException))
                         {
                             context.Response.Headers.Add("Token-Expired", "true");
                             context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
                             context.Response.ContentType = "application/json";
                             var result = JsonHelper.ObjectToJson(new ResultJson() { resultCode = 401, errMsg = "Unauthorized" });

                             MemoryStream stream = new MemoryStream();
                             StreamWriter writer = new StreamWriter(stream);
                             writer.Write(result);
                             writer.Flush();

                             context.Response.Body = stream;

                             context.Fail(result);
                         }
                         return Task.CompletedTask;
                     },
                     OnTokenValidated = context =>
                     {
                         var tokenString = context.Request.Headers["Authorization"].ToString().Replace("Bearer ", "");
                         var tokenModel = TokenBll.GetModel(tokenString);
                         if (tokenModel == null)
                         {
                             context.Response.Headers.Add("Token-Expired", "true");
                             context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
                             context.Response.ContentType = "application/json";
                             var result = JsonHelper.ObjectToJson(new ResultJson() { resultCode = 401, errMsg = "Unauthorized" });

                             MemoryStream stream = new MemoryStream();
                             StreamWriter writer = new StreamWriter(stream);
                             writer.Write(result);
                             writer.Flush();

                             context.Response.Body = stream;

                             context.Fail(result);
                         }
                         return Task.CompletedTask;
                     }
                 };
             });
        }
    }
}
